package com.ckx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ckx.constants.SystemConstants;
import com.ckx.domain.dto.ArticleAddDto;
import com.ckx.domain.dto.ArticleQueryDto;
import com.ckx.domain.dto.ArticleUpdateDto;
import com.ckx.domain.entity.Article;
import com.ckx.domain.entity.ArticleTag;
import com.ckx.domain.entity.Category;
import com.ckx.domain.entity.Tag;
import com.ckx.domain.vo.*;
import com.ckx.enums.AppHttpCodeEnum;
import com.ckx.exception.SystemException;
import com.ckx.mapper.ArticleMapper;
import com.ckx.mapper.ArticleTagMapper;
import com.ckx.mapper.TagMapper;
import com.ckx.service.ArticleService;
import com.ckx.service.ArticleTagService;
import com.ckx.service.CategoryService;
import com.ckx.utils.BeanCopyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ArticleTagService articleTagService;
    @Autowired
    private TagMapper tagMapper;

    @Override
    public List<HotArticleVo> hotArticleList() {

        //返回 10条热门作品
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        //要求已发布
        wrapper.lambda().eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);//0  已发布
        //按浏览量降序
        wrapper.lambda().orderByDesc(Article::getViewCount);
//        List<Article> articles = this.list(wrapper);
        Page<Article> page = new Page<>(1, 10);
        page(page, wrapper);

        List<HotArticleVo> hotArticleVos = BeanCopyUtil.copyBeanList(page.getRecords(), HotArticleVo.class);

        return hotArticleVos;

    }

    @Override
    public PageVo articleList(Integer pageNum, Integer pageSize, Long categoryId) {

        //查询条件
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        // 如果 有categoryId 就要 查询时要和传入的相同
        wrapper.lambda().eq(Objects.nonNull(categoryId) && categoryId > 0, Article::getCategoryId, categoryId);
        // 状态是正式发布的
        wrapper.lambda().eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
        // 对isTop进行降序
        wrapper.lambda().orderByDesc(Article::getIsTop);
        //分页查询
        Page<Article> page = new Page<>(pageNum, pageSize);
        page(page, wrapper);

        //查询categoryName
        List<Article> articles = page.getRecords();
        articles.stream().map(article -> {
            article.setCategoryName(categoryService.getById(article.getCategoryId()).getName());
            return article;
        }).collect(Collectors.toList());

        //封装 vo
        List<ArticleListVo> articleListVos = BeanCopyUtil.copyBeanList(articles, ArticleListVo.class);

        return new PageVo(articleListVos, page.getTotal());

    }

    @Override
    public ArticleDetailVo getArticleDetail(Long id) {

        //根据id查询文章
        Article article = this.getById(id);

        //转换成VO
        ArticleDetailVo articleDetailVo = BeanCopyUtil.copyBean(article, ArticleDetailVo.class);
        //根据分类id查询分类名
        Long categoryId = articleDetailVo.getCategoryId();
        Category category = categoryService.getById(categoryId);
        if (category != null) {
            articleDetailVo.setCategoryName(category.getName());
        }

        return articleDetailVo;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addArticle(ArticleAddDto articleAddDto) {
        //存储文章
        Article article = BeanCopyUtil.copyBean(articleAddDto, Article.class);
        this.save(article);

        //存储文章与标签关系
        List<Long> tags = articleAddDto.getTags();
        //封装成存储类型
        List<ArticleTag> articleTagList = tags.stream()
                .map(tag -> new ArticleTag(article.getId(), tag))
                .collect(Collectors.toList());
        articleTagService.saveBatch(articleTagList);

    }

    @Override
    public PageVo listByPage(Integer pageNum, Integer pageSize, ArticleQueryDto articleQueryDto) {
        //查询
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .like(StringUtils.hasText(articleQueryDto.getTitle()), Article::getTitle, articleQueryDto.getTitle())
                .or()
                .like(StringUtils.hasText(articleQueryDto.getSummary()), Article::getSummary, articleQueryDto.getSummary());
//        wrapper.lambda().eq(Article::getDelFlag, SystemConstants.NOT_DELFLAG);

        Page<Article> page = new Page<>(pageNum, pageSize);
        page(page, wrapper);

        List<ArticleVo> articleVoList = page.getRecords().stream()
                .map(obj -> BeanCopyUtil.copyBean(obj, ArticleVo.class))
                .collect(Collectors.toList());

        //封装vo
        return new PageVo(articleVoList, page.getTotal());

    }

    @Override
    public ArticleVo getArticleInfo(Long id) {
        //获取对应文章
        Article article = this.getById(id);
        if (Objects.isNull(article)) {
            throw new SystemException(AppHttpCodeEnum.ARGS_FAIL);
        }
        //封装vo
        ArticleVo articleVo = BeanCopyUtil.copyBean(article, ArticleVo.class);
        //todo 前端有问题，即使下列数据返回也不能正确显示,暂时不返回
        //获取文章对应标签
        QueryWrapper<ArticleTag> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ArticleTag::getArticleId, article.getId());
        List<ArticleTag> articleTags = articleTagService.getBaseMapper().selectList(wrapper);

        List<TagVo> tagVos = new ArrayList<>();
        articleTags.forEach(articleTag -> {
            Tag tag = tagMapper.selectById(articleTag.getTagId());
            tagVos.add(BeanCopyUtil.copyBean(tag, TagVo.class));
        });
        articleVo.setTags(tagVos);
        return articleVo;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateArticle(ArticleUpdateDto articleUpdateDto) {
        //更新文章
        Article article = BeanCopyUtil.copyBean(articleUpdateDto, Article.class);
        this.updateById(article);

        //更新文章标签关联表
        //先删除
        QueryWrapper<ArticleTag> wrapper = new QueryWrapper<>();
        if (articleTagService.remove(wrapper.lambda().eq(ArticleTag::getArticleId, article.getId()))) {
            //再插入
            List<TagVo> tags = articleUpdateDto.getTags();
            List<ArticleTag> articleTagList = tags.stream()
                    .map(tagVo -> new ArticleTag(article.getId(), tagVo.getId()))
                    .collect(Collectors.toList());

            articleTagService.saveBatch(articleTagList);
        }
    }

    @Override
    public void remove4DelFlag(Long id) {
        if (Objects.isNull(id) && id <= 0){
            throw new SystemException(AppHttpCodeEnum.ARGS_FAIL);
        }
        UpdateWrapper<Article> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(Article::getDelFlag, SystemConstants.DELFLAG);
        wrapper.lambda().eq(Article::getId, id);
        this.update(wrapper);
    }
}
